
#ifndef _TTG_PIPELINE_NODE_
#define _TTG_PIPELINE_NODE_

#include "DataStreamNode.h"

namespace ttg
{
	namespace pipeline
	{
		//Viewable for user node.
		template <class InType, class OutType>
		class Node :public ttg_internal::pipeline::DataStreamNode<InType, OutType, InType, OutType>
		{
			private:
				//Hiding ContextID.
				virtual void onEnd(ttg::pipeline::ContextID ID)
				{
					if (ID == getIContext().getRootContextID())
						onEnd();
					//{ printf("%s.onEnd()\n", getInfo().getName()); }
				}
				//Hiding ContextID.
				virtual void process(ttg::pipeline::ContextID ID, InType data)
				{ process(data); }
				//Hiding ContextID.
				virtual void onBegin(ttg::pipeline::ContextID ID)
				{
					if (ID == getIContext().getRootContextID())
						onBegin();
				}
			protected:
				//Will be called before data processing.
				virtual void onBegin()
				{ /*nothing*/ }
				//Processes received data.
				virtual void process(InType data) = 0;
				//Will be called after data processing.
				virtual void onEnd()
				{ /*nothing*/ }
			public:
				inline Node(const char *name = "__UNNAMED",
							bool is_serial = false)
					:DataStreamNode(name, is_serial)
				{
					onDataReceive() += structures::make_delegate(this, repackData);
				}
				static void repackData(Node *object, ttg_internal::pipeline::DataSet *data_set)
				{
					//Creating vector with data.
					ttg::structures::UniversalStack &buffer = data_set->getBuffer();
					std::vector<InType> data;
					while (!buffer.isEmpty())
					{
						data.push_back(buffer.pop<InType>());
					}
					//Creating and sending tasks.
					data_set->addTasks(object->createAndRegisterTasks(data, data_set->getContextID()));
				}
		};
	}
}

#endif
